package com.caissa.springboot.starter.permission.service;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import com.caissa.ecp.base.api.dto.po.PermissionPo;
import com.base.springboot.starter.redis.service.RedisService;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;

/**
 * @author yuzhongbo
 * @date 2020/5/12 PM2:11
 */
@Aspect
@Order(10)
@Slf4j
public class PermissionAspect {
    @Autowired
    private RedisService redisService;

    @Around("@within(com.base.springboot.starter.permission.service.CheckLogin) || @annotation(com.base.springboot.starter.permission.service.CheckLogin)")
    public Object checkLogin(ProceedingJoinPoint point) throws Throwable {
        this.checkToken();
        return point.proceed();
    }

    @Around("@within(com.base.springboot.starter.permission.service.CheckPermission) || @annotation(com.base.springboot.starter.permission.service.CheckPermission)")
    public Object checkPermission(ProceedingJoinPoint point) throws Throwable {
        this.checkToken();
        this.checkPermissionKey();
        return point.proceed();
    }

    /**
     * 验证Token
     */
    private void checkToken() {
        try {
            HttpServletRequest request = getHttpServletRequest();
            String token = request.getHeader(TokenConstant.xToken);
            String userId = request.getHeader(TokenConstant.xId);

            if (StrUtil.isBlank(userId) && StrUtil.isNotBlank(token)) {
                JSONObject userJsonObject = AesTokenUtil.getUserJsonObject(token);
                userId = userJsonObject.getStr(TokenConstant.id);
                String tokenType = userJsonObject.getStr(TokenConstant.tokenType);

                request.setAttribute(TokenConstant.xId, userJsonObject.getStr(TokenConstant.id));
                request.setAttribute(TokenConstant.xTokenType, tokenType);

                if (TokenConstant.B_TOKEN.equals(tokenType)) {
                    request.setAttribute(TokenConstant.xBtSystem, userJsonObject.getStr(TokenConstant.btSystem));
                    request.setAttribute(TokenConstant.xName, userJsonObject.getStr(TokenConstant.name));
                    request.setAttribute(TokenConstant.xLoginCode, userJsonObject.getStr(TokenConstant.loginCode));
                } else {
                    request.setAttribute(TokenConstant.xId, userJsonObject.getStr(TokenConstant.id));
                    request.setAttribute(TokenConstant.xPhone, userJsonObject.getStr(TokenConstant.phone));
                }
            }

            if (StrUtil.isBlank(userId)) {
                throw new SecurityException("该用户无可用信息！");
            }
        } catch (Exception e) {
            throw new SecurityException("该用户获取异常！");
        }
    }

    /**
     * 验证是否有该权限
     *
     * @return
     */
    public void checkPermissionKey() {
        try {
            HttpServletRequest request = getHttpServletRequest();
            String permissionKey = request.getHeader(TokenConstant.permissionKey);
            if (StrUtil.isNotBlank(permissionKey)) {
                String token = request.getHeader(TokenConstant.xToken);
                String userId = request.getHeader(TokenConstant.xId);
                String bySystem = request.getHeader(TokenConstant.xBtSystem);

                if (StrUtil.isBlank(userId) && StrUtil.isNotBlank(token)) {
                    JSONObject userJsonObject = AesTokenUtil.getUserJsonObject(token);
                    userId = userJsonObject.getStr(TokenConstant.id);
                    bySystem = userJsonObject.getStr(TokenConstant.btSystem);
                }

                if (userId != null && StrUtil.isNotBlank(permissionKey)) {
                    String redisKey = PermissionService.REDIS_PREFIX_USER_PERMISSION + bySystem + "_" + userId;
                    Map<Long, PermissionPo> permissionPos = (Map<Long, PermissionPo>) redisService.get(redisKey);
                    PermissionPo permissionPo = permissionPos.get(permissionKey);
                    if (permissionPo == null) {
                        throw new SecurityException("该用户权限信息为空！");
                    }
                } else {
                    throw new SecurityException("该用户信息或权限为空！");
                }
            }
        } catch (Exception e) {
            throw new SecurityException("该用户无权限访问");
        }
    }

    /**
     * 获取HttpServletRequest
     *
     * @return
     */
    private HttpServletRequest getHttpServletRequest() {
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes attributes = (ServletRequestAttributes) requestAttributes;
        return attributes.getRequest();
    }
}